package org.biloxi.player.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import org.biloxi.model.Deck;
import org.biloxi.model.GameState;
import org.biloxi.model.GameState.Phase;
import org.biloxi.model.magicobjects.MagicObject;
import org.biloxi.model.magicobjects.impl.Plains;
import org.biloxi.model.magicobjects.impl.Swamp;
import org.biloxi.model.magicobjects.impl.VenomousDragonFly;
import org.biloxi.model.player.PlayerState;
import org.biloxi.model.player.Zone;
import org.biloxi.player.Player;
import org.biloxi.player.PlayerID;
import org.biloxi.player.actions.ActionOptionPair;
import org.biloxi.player.actions.PlayerActionRepository;

public class ConsolePlayer extends Player {

	private final PlayerID _id;
	private final Deck _deck = new Deck();
	
	public ConsolePlayer(PlayerActionRepository acts, String id) {
		super(acts);

		_deck.cards.add(Swamp.class.getSimpleName());
		_deck.cards.add(VenomousDragonFly.class.getSimpleName());
		_deck.cards.add(Plains.class.getSimpleName());
		
		_id = new PlayerID(id);
	}
	
	protected void printZone(String zName, Zone z){
		System.out.println(zName);
		for(MagicObject mo : z.getMagicObjects()){
			System.out.println("\tcardId:"+mo.getCardID()+" "+mo.getCardName()+" - "+mo.getDescription());
		}
	}

	public ActionOptionPair<?>[] getAction(GameState gameState, PlayerState playerState) {
		//TODO: allow main1 phase to continue after playing a card
		//TODO: ask which land to tap for mana and allow main1 phase to continue
		//TODO: allow main2 phase to play a card
		
		//if(gameState.getPhase() == Phase.Upkeep){
			//TODO remove this debug info
			//only print out the info during upkeep
			System.out.println("PlayerID:"+getID().toString());
			System.out.println("PHASE:"+gameState.getPhase().toString());
			System.out.println("-----------------");
			printZone("LIBRARY", playerState.getLibrary());
			printZone("HAND", playerState.getHand());
			printZone("IN_PLAY", playerState.getInPlay());
			System.out.println("-----------------\n");
		//}
		
		if(gameState.getPhase() == Phase.Draw){
			//draw a card
			return new ActionOptionPair<?>[]{actions.drawCard.do_(null)};
		}else if(gameState.getPhase() == Phase.Main1){
			System.out.println("What do you want to do?");
			
			//check for lands to tap
			List<MagicObject> cardsInPlay = playerState.getInPlay().getMagicObjects();
			List<MagicObject> landsInPlay = gameState.getType("land",cardsInPlay);
			if(landsInPlay.size() > 0){
				System.out.println("A) tap a land for mana."); //TODO: add options for each specific untapped land
			}
			
			//check for cards in hand to play
			List<MagicObject> cardsInHand = playerState.getHand().getMagicObjects();
			if(cardsInHand.size() > 0){
				System.out.println("B) play a card from your hand.");
			}
			
			//skip to combat phase
			System.out.println("C) skip to combat phase.");
			
			//get player input
			String cmdIn = null;
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			try {
		         cmdIn = br.readLine();
		    } catch (IOException e) {
		         e.printStackTrace();
		         return null;
		    }
		    if(cmdIn.equals("A")){
		    	//not implemented
		    	System.out.println("tapping land is not implemented.");
		    	return null;
		    }
		    else if(cmdIn.equals("B")){
		    	String cardIDIn = null;
		    	Long cardIDinNum = null;
		    	System.out.println("What is the card id of the card you would like to play?");
		    	try {
					cardIDIn = br.readLine();
					cardIDinNum = Long.parseLong(cardIDIn);
					
				} catch (IOException e) {
					e.printStackTrace();
					return null;
				} catch (java.lang.NumberFormatException e){
					System.out.println("card with cardID of "+cardIDIn+" not found");
					return getAction(gameState, playerState);
				}
				
				for(MagicObject cardInHand : cardsInHand){
					if(cardInHand.getCardID() == Long.parseLong(cardIDIn)){
						if(cardInHand.getType().equals("land")){
							//TODO limit user to laying one land per turn
							return new ActionOptionPair<?>[]{actions.playCard.do_(cardInHand)};
						}
						else {
							//TODO: check if mana pool has correct mana to play this card and reduce it
							return new ActionOptionPair<?>[]{actions.playCard.do_(cardInHand)};
						}
					}
				}
				System.out.println("card with cardID of "+cardIDIn+" not found");
				return getAction(gameState, playerState);
		    }
		    else if(cmdIn.equals("C")){
		    	return null;
		    }
		    else{
		    	System.out.println("unrecognized command");
		    	return getAction(gameState, playerState);
		    }
		}else{
			return null;
		}
	}

	public Deck getDeck() {
		return _deck;
	}

	public PlayerID getID() {
		return _id;
	}

}
